package com.avblog.console.convert;

import java.util.List;
import java.util.ArrayList;
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class Converter{
	
	//private static String kwpattern = "(package|abstract|import|class|public|private|protected|new|static)|((void|byte|boolean|int|long|float|double)(\\[\\])?)";
	private static String kwpattern = "(package|abstract|import|class|public|private|protected|new|static|void)( ){1}|(\\()?(byte|boolean|int|long|float|double)[(\\[\\])? \\]]";
	private static String[] keywords = {"package", "import", "class", "interface", "public", "protected", "private", "new", "void", "int", "if", "while", "for", "try", "catch", "finally", "null", "throws"};
	
	Pattern pattern = null;
	private String fullSourceName;
	private List<String> gutters = null;
	private ArrayList<String> codes = new ArrayList<String>();
	private List<String> convertedCodes = new ArrayList<String>();
	
	public Converter(){
		pattern = Pattern.compile(kwpattern);
	}
	
	public int getNumOfLine(){
		return codes.size();
	}
	
	public ArrayList<String> getLinesOfCode(){
		return codes;
	}
	
	public List<String> getConvertedCodes(){
		return convertedCodes;
	}
	
	public String getFullSourceName(){
		return fullSourceName;
	}
	
	public void setFullSourceName(String sourceFileName){
		this.fullSourceName = sourceFileName;
	}
	
	public void readSourceFile(String sourcePath) throws IOException{
		FileReader fr = null;
		String line;
		
		try{
			fr = new FileReader(sourcePath);
			BufferedReader reader = new BufferedReader(fr);
			while( (line = reader.readLine()) != null ){
				codes.add(line);
			}
			
		}catch(IOException ex){
			ex.printStackTrace();
		}
		finally{
			if(fr != null)
				fr.close();
		}
	}
	
	public void readSourceFile(File source) throws IOException{
		FileReader fr = null;
		String line;
		
		try{
			fr = new FileReader(source);
			BufferedReader reader = new BufferedReader(fr);
			while( (line = reader.readLine()) != null ){
				codes.add(line);
				System.out.println(line);
			}
			
		}catch(IOException ex){
			ex.printStackTrace();
		}
		finally{
			if(fr != null)
				fr.close();
		}
	}
	
	public List<String> getGutter(){
		if(gutters == null){
			gutters = new ArrayList<String>();
			int nLines = codes.size();
			for(int i=1; i<=nLines; i++){
				gutters.add("<div class=\"line\">" + i + "</div>");
			}
		}
		
		return gutters;
	}
	
	public void doConvert(){
		int i, j, nLines = codes.size();
		String[] tokens;
		String line;
		for(i=0; i<nLines; i++){
			line = processOnLine(codes.get(i));
			convertedCodes.add(line);
		}
	}
	
	public String processOnLine(String line){
		String kwgroup="", s, result = "";
		int start, end, i = 0;
		boolean hasMatched = false;
		Matcher matcher;
		matcher = pattern.matcher(line);
		
		while(matcher.find()){
			hasMatched = true;
			start = matcher.start();
			end = matcher.end();
			
			s = line.substring(start, end);
			System.out.println("Match: " + s);
			//check if there is something non-keyword appear before this matched keyword
			if( i < start ){
				String gapBtw = line.substring(i, start).trim();
				System.out.println("GAP BETWEEN KW: " + gapBtw);
				if( !("".equals(gapBtw)) ){
					//Got spaces right before a keyword
					kwgroup = kwgroup + " " + s;
					System.out.println("KWGROUP(1): " + kwgroup + "; Match@(" + start + "," + end + ")");
				}else{
					//No, there isn't any space before this keyword
					
					if(kwgroup.length() > 0){
						result = result + "<code class=\"keyword\">" + kwgroup + "</code>";
						System.out.println("KWGROUP(2): " + kwgroup + "; Match@(" + start + "," + end + ")");
					}
					
					kwgroup = s;
					System.out.println("KWGROUP(3): " + kwgroup + "; Match@(" + start + "," + end + ")");
					
					s = line.substring(i, start);
					if(s.trim().length() <= 0){
						s = s.replaceAll(" ", "&nbsp;");
						s = s.replaceAll("\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
						result = result + s;
					}else{
						s = s.replaceAll(" ", "&nbsp;");
						s = s.replaceAll("\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
						result = result + "<code>" + s + "</code>";
					}
				}
			}else{
				kwgroup = kwgroup + s;
				System.out.println("KWGROUP(4): " + kwgroup + "; Match@(" + start + "," + end + ")");
			}
				
			i = end;
		}
		
		if(kwgroup.length() > 0){
			result = result + "<code class=\"keyword\">" + kwgroup + "</code>";
			kwgroup = "";
		}
		
		if(!hasMatched){
			System.out.println(line);
			s = line.replaceAll(" ", "&nbsp;");
			s = s.replaceAll("\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
			System.out.println("<code>" + s + "</code>\n");
			return ("<code>" + s + "</code>");
		}
			
		if(i < line.length() && line.substring(i, line.length()).length() > 0){
			result = result + "<code>" + line.substring(i) + "</code>";
		}
		
		System.out.println(line);
		System.out.println(result + "\n");
		return result;
	}
	
	public List<WordRun> processLine(String line){
		int i = 0;
		String token="", s = "", tmp = line;
		List<WordRun> result = new ArrayList<WordRun>();
		List<WordRun> listTmp;
		WordRun wr;
		String[] words;
		
		//count space and tab character
		while(line.charAt(i) == ' ' || line.charAt(i) == '\t'){
			token = token + line.charAt(i);
			i++;
		}
		
		if(token.length()>0){
			result.add(new WordRun(token));
			tmp = line.substring(i);
		}
		
		//Check if there is inline comment in this line of code
		i = tmp.indexOf("//");
		if(i >= 0){
			wr =  new WordRun( tmp.substring(i) );
			wr.setKind(WordRunKind.INLINE_COMMENT);
			result.add(wr);
			tmp = tmp.substring(0, i);
		}
		
		words = tmp.split(" ");
		for(i=0; i<words.length; i++){
			token = words[i].trim();
			if(token.contains("(")){
				listTmp = dealWithParenthese(token, ' ');
				result.addAll(listTmp);
			}else{
				wr =  new WordRun(token);
				wr.setUseNextChar(true);
				result.add(wr);
			}
		}	

		return result;
	}
	
	
	/**
		Check if a word contains '('. If yes, we split the word into sub-word with delimiter is '('
		@param
			String word: word to be determined
			char lastChar: the nextChar of the last word
			
		@return
			
	*/
	private List<WordRun> dealWithParenthese(String word, char lastChar){
		List<WordRun> result = new ArrayList<WordRun>();
		WordRun wr;
		String[] words = word.split("\\(");
		int i;
		
		if(words.length <= 0)
			return result;
			
		if(word.charAt(0) == '('){
			wr = new WordRun("(");
			result.add(wr);
		}
		
		for(i=0; i<words.length-1; i++){
			wr = new WordRun(words[i], '(');
			result.add(wr);
		}
		
		if(word.charAt(word.length()-1) == '('){
			wr = new WordRun(words[words.length-1]+"(", lastChar);
			result.add(wr);
			return result;
		}
		
		wr = new WordRun(words[words.length-1], lastChar);
		result.add(wr);
		
		return result;
	}
}
